package org.luxor.eshop.account.service.impl;

import io.seata.rm.tcc.api.BusinessActionContext;
import org.luxor.commons.core.exception.TransactionException;
import org.luxor.commons.redis.plugin.idempotent.service.IdempotentService;
import org.luxor.eshop.account.mapper.AccountMapper;
import org.luxor.eshop.account.service.ReceiptTccAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * TCC 收款
 *
 * @author Mr.Yan  @date: 2020/12/8
 */
@Component
public class ReceiptTccActionImpl implements ReceiptTccAction {
    private static final Logger logger = LoggerFactory.getLogger(ReceiptTccActionImpl.class);

    @Resource
    private IdempotentService idempotentService;
    @Resource
    private AccountMapper accountMapper;

    @Override
    @Transactional(rollbackFor = TransactionException.class)
    public boolean prepare(BusinessActionContext actionContext, Long billCode, String receiptAccount, BigDecimal amounts) {
        // 生成幂等验证token
        idempotentService.register("ReceiptTccAction", "Receipt-" + actionContext.getXid());

        // 预冻结资源
        accountMapper.prepareReceipt(amounts, receiptAccount);
        logger.info("TTC收款 - [第一阶段：预留资源(Prepare)],执行成功");
        return true;
    }

    @Override
    @Transactional(rollbackFor = TransactionException.class)
    public boolean commit(BusinessActionContext actionContext) {
        // 幂等控制
        boolean checkResult = idempotentService.questionPass("ReceiptTccAction", "Receipt-" + actionContext.getXid());
        if (checkResult) {
            BigDecimal amounts = new BigDecimal(actionContext.getActionContext().get("amounts").toString());
            String receiptAccount = actionContext.getActionContext().get("receiptAccount").toString();
            accountMapper.commitReceipt(amounts, receiptAccount);
            logger.info("TTC收款 - [第二阶段：确认/提交(Commit)],执行成功");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = TransactionException.class)
    public boolean rollback(BusinessActionContext actionContext) {
        logger.info("TTC收款 - [第二阶段：取消/回滚(Rollback)],开始执行...", actionContext.getXid());
        // 解决空回滚&幂等控制
        boolean checkResult = idempotentService.questionPass("ReceiptTccAction", "Receipt-" + actionContext.getXid());
        if (checkResult) {
            BigDecimal amounts = new BigDecimal(actionContext.getActionContext().get("amounts").toString());
            String receiptAccount = actionContext.getActionContext().get("receiptAccount").toString();
            accountMapper.rollbackReceipt(amounts, receiptAccount);
            logger.info("TTC收款 - [第二阶段：取消/回滚(Rollback)],执行成功");
        }
        return true;
    }
}
